home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ddj1291.zip / STAT.ZIP / SOURCE.ZIP / PARDMAP.C < prev    next >
C/C++ Source or Header  |  1990-05-09  |  13KB  |  413 lines

  1. /*
  2. ** File:    pardmap.c
  3. **
  4. **        Copyright 1990
  5. **        Fred Motteler and Applied Microsystems Corporation
  6. **        All Rights Reserved
  7. **
  8. ** Description:    This file contains a generic link map (memory map) reader and
  9. **        the necessary support routines.  A stand alone tester is
  10. **        included.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include "padef.h"
  18.  
  19. /* This is a table of pointers to mapdata structures. */
  20. struct padata *patableAHP[PAMAX];
  21.  
  22. /*
  23. ** Function:    int pardmap( FILE *mapFP, FILE *formatFP,
  24. **                 unsigned long originL, processedNP )
  25. **
  26. ** Description:    This is a generic map file reader.
  27. **
  28. **        The map is contained in the file with file pointer mapFP.
  29. **
  30. **        Format information about the map file is in the file with
  31. **        file pointer formatFP.
  32. **
  33. **        The value of originL gives the offset of the map zero point
  34. **        relative to the start of memory.  For MS-DOS and any system
  35. **        that relocates the executable image, this value is the start
  36. **        of the program in memory.
  37. **
  38. **        The format of the map file is assumed to be:
  39. **
  40. **            [[initial information to ignore]
  41. **            start of symbolic information identifier]
  42. **            symbolic information
  43. **            [end of symbolic information identifier
  44. **            [final information to ignore]]
  45. **
  46. **        The format of the symbol information is assumed to be:
  47. **
  48. **            symbol value
  49. **        or
  50. **            value symbol
  51. **
  52. **        where value may be segmented.
  53. **
  54. **            segment:offset
  55. **
  56. **        or linear:
  57. **
  58. **            value
  59. **
  60. **        Information about the:
  61. **
  62. **            "start of symbolic information identifier"
  63. **            "end of symbolic information identifier"
  64. **            symbol value order
  65. **            symbol line format
  66. **            lines to skip
  67. **
  68. **        is given in the map format file in ASCII format:
  69. **
  70. **            PA_START_ID:"string to look for to start symbolic info"
  71. **            PA_END_ID:"string to look for to end symbolic info"
  72. **            PA_ORDER:"sym val"    (for linear address)
  73. **                 "val sym"
  74. **                 "sym seg:off"    (for segmented address)
  75. **                 "seg:off sym"
  76. **            PA_FORMAT:"scanf format string for reading values"
  77. **            PA_SKIP_ID:"string to look for on line to ignore"
  78. **
  79. **        Note that map file lines containing the START_ID, END_ID,
  80. **        and SKIP_ID strings are not processed for symbolic information.
  81. **
  82. **        The order and format fields are required to allow use of
  83. **        the ANSI sscanf() function.
  84. **
  85. **        The entries in the map format file may be in any order.
  86. **    
  87. **        Upon exit, the maptableAHP array contains pointers to mapdata
  88. **        structures that contain address and symbol name information.
  89. **        The table is sorted according to absolute address value.  Note
  90. **        that all segment:offset data is converted to linear address
  91. **        values.
  92. **
  93. **        The location pointed to by processedNP is updated with the
  94. **        number of symbol processed.
  95. **
  96. **        The returned value is zero if the map read operation was
  97. **        successful.  Otherwise an error code is returned.
  98. */
  99. int
  100. pardmap(mapFP, formatFP, originL, processedNP)
  101. FILE *mapFP;            /* Map file to read */
  102. FILE *formatFP;            /* File with map file format information */
  103. unsigned long originL;        /* Program origin offset */
  104. int *processedNP;        /* Pntr to count of symbols processed */
  105. {
  106.     unsigned long valueL;    /* Value of current symbol */
  107.     unsigned int offsetW;    /* Offset part of current symbol */
  108.     unsigned int segmentW;    /* Offset part of current symbol */
  109.     char symbolAB[PA_LINE_LEN];    /* Current symbol string */
  110.     struct padata *tempHP;    /* Temp pntr to map data structure */
  111.     char lineAB[PA_LINE_LEN];    /* Input line buffer */
  112.     int linelenN;        /* Length of input line */
  113.     char startAB[PA_LINE_LEN];    /* Start line identifier */
  114.     char endAB[PA_LINE_LEN];    /* End line identifier */
  115.     char orderAB[PA_LINE_LEN];    /* Symbol value order string */
  116.     char formatAB[PA_LINE_LEN];    /* Symbol value format string */
  117.     char skip1AB[PA_LINE_LEN];    /* Skip line identifier */
  118.     char skip2AB[PA_LINE_LEN];    /* Skip line identifier */
  119.     int errorN;            /* Error code */
  120.     int symorderN;        /* Gives symbol value order and type */
  121.     int i;            /* General index */
  122.  
  123.     /* Read in map file delimiters from the map configuration file. */
  124.     if ((errorN = paconfig(formatFP, PA_START_ID, startAB)) != 0)
  125.     return(errorN);
  126.     if ((errorN = paconfig(formatFP, PA_END_ID, endAB)) != 0)
  127.     return(errorN);
  128.     if ((errorN = paconfig(formatFP, PA_ORDER, orderAB)) != 0)
  129.     return(errorN);
  130.     if ((errorN = paconfig(formatFP, PA_FORMAT, formatAB)) != 0)
  131.     return(errorN);
  132.     if ((errorN = paconfig(formatFP, PA_SKIP1_ID, skip1AB)) != 0)
  133.     return(errorN);
  134.     if ((errorN = paconfig(formatFP, PA_SKIP2_ID, skip2AB)) != 0)
  135.     return(errorN);
  136.  
  137. #ifdef TEST
  138.     printf(" start string: %s\n",startAB);
  139.     printf("   end string: %s\n",endAB);
  140.     printf(" order string: %s\n",orderAB);
  141.     printf("format string: %s\n",formatAB);
  142.     printf("  skip string: %s\n",skip1AB);
  143.     printf("  skip string: %s\n",skip2AB);
  144. #endif
  145.  
  146.     /* Determine the symbol value order and type. */
  147.     if (strcmp(PA_SV_ID,orderAB) == 0)
  148.     symorderN = PA_SYM_VAL;
  149.     else if (strcmp(PA_VS_ID,orderAB) == 0)
  150.     symorderN = PA_VAL_SYM;
  151.     else if (strcmp(PA_SSO_ID,orderAB) == 0)
  152.     symorderN = PA_SYM_SEG;
  153.     else if (strcmp(PA_SOS_ID,orderAB) == 0)
  154.     symorderN = PA_SEG_SYM;
  155.     else
  156.     return(PA_BAD_ORDER_E);
  157.  
  158.     /* Skip initial part of map file that is not used. */
  159.     if (startAB[0] != '\0')
  160.     {
  161.     while (fgets(lineAB, PA_LINE_LEN, mapFP) != (char *) NULL)
  162.     {
  163.         /* Search the line for the string in startAB that starts
  164.          * the map data. */
  165.         if (strstr(lineAB, startAB) != (char *) NULL)
  166.         break;
  167.     }
  168.     }
  169.  
  170.     /* Initialize the number of address/symbol pairs processed. */
  171.     *processedNP = 0;
  172.     patableAHP[0] = (struct padata *) NULL;
  173.  
  174.     /* Read symbol section of the map file */
  175.     while (fgets(lineAB, PA_LINE_LEN, mapFP) != (char *) NULL)
  176.     {
  177.     /* Check if the line is blank */
  178.     linelenN = strlen(lineAB);
  179.     for (i = 0; i < linelenN; i++)
  180.     {
  181.         if (isalnum(lineAB[i]))
  182.         break;
  183.     }
  184.     if (i == linelenN)
  185.         continue;
  186.     /* Search line for the string endAB that ends the map data. */
  187.     if ((endAB[0] != '\0') && (strstr(lineAB, endAB) != (char *) NULL))
  188.         break;
  189.     /* Search line for either string skip1AB or skip2AB that indicate
  190.      * the line is to be skipped. */
  191.     if ((skip1AB[0] != '\0') && (strstr(lineAB, skip1AB) != (char *) NULL))
  192.         continue;
  193.     if ((skip2AB[0] != '\0') && (strstr(lineAB, skip2AB) != (char *) NULL))
  194.         continue;
  195.  
  196. #ifdef TEST
  197.     printf("Line to process: %s\n",lineAB);
  198. #endif
  199.     /* The line is ok, process the symbol data that it contains. */
  200.     switch(symorderN)
  201.     {
  202.       case PA_SYM_VAL:
  203.         /* Symbol / linear value format - note that valueL is a long! */
  204.         if (sscanf(lineAB,formatAB,symbolAB,&valueL) != 2)
  205.         {
  206.         /* In some situations (Intermetrics), the symbol value may
  207.          * be on one line, and the rest of the value information is
  208.          * on the next line.  Try appending the next line to the
  209.          * current line, and then retry the operation. */
  210.         for (i = 0; !iscntrl(lineAB[i]); i++);
  211.         if (fgets((&(lineAB[i])), PA_LINE_LEN, mapFP) != (char *) NULL)
  212.         {
  213.             if (sscanf(lineAB,formatAB,symbolAB,&valueL) != 2)
  214.             return(PA_MAP_FMT_E);
  215.         }
  216.         else
  217.             return(PA_MAP_FMT_E);
  218.         }
  219.         valueL += originL;
  220.         break;
  221.       case PA_VAL_SYM:
  222.         /* Linear value / symbol format - note that valueL is a long! */
  223.         if (sscanf(lineAB,formatAB,&valueL,symbolAB) != 2)
  224.         return(PA_MAP_FMT_E);
  225.         valueL += originL;
  226.         break;
  227.       case PA_SYM_SEG:
  228.         /* Symbol / segmented value format - note that segmentW and
  229.          * offsetW are ints! */
  230.         if (sscanf(lineAB,formatAB,symbolAB,&segmentW,&offsetW) != 3)
  231.         return(PA_MAP_FMT_E);
  232.         valueL = (unsigned long) segmentW;
  233.         valueL <<= 4;
  234.         valueL += (unsigned long) offsetW;
  235.         valueL += originL;
  236.         break;
  237.       case PA_SEG_SYM:
  238.         /* Segmented value / symbol format - note that segmentW and
  239.          * offsetW are ints! */
  240.         if (sscanf(lineAB,formatAB,&segmentW,&offsetW,symbolAB) != 3)
  241.         return(PA_MAP_FMT_E);
  242.         valueL = (unsigned long) segmentW;
  243.         valueL <<= 4;
  244.         valueL += (unsigned long) offsetW;
  245.         valueL += originL;
  246.         break;
  247.       default:
  248.         return(PA_BAD_ORDER_E);
  249.     }
  250.  
  251.     /* Check if the symbol starts with a numeric digit.  If so, then
  252.      * throw the symbol entry out. */
  253.     if (isdigit((symbolAB[0])))
  254.         continue;
  255.  
  256.     /* A valid symbol value is in valueL, and a valid symbol name
  257.      * is in symbolAB, check if we have room in the table for this
  258.      * entry.  The extra three is to allow room for a "beginning of
  259.      * memory symbol", an "end of memory symbol" and a NULL pointer
  260.      * table terminator. */
  261.     if ((*processedNP) >= (PAMAX - 3))
  262.         return(PA_TAB_FULL_E);
  263.  
  264.     /* There is room, allocate space for the actual symbol info. */
  265.     if ((tempHP = (struct padata *) malloc (sizeof(struct padata)))
  266.         == (struct padata *) NULL)
  267.         return(PA_NO_MEM_E);
  268.  
  269.     /* Enter the symbol into the table. */
  270.     patableAHP[((*processedNP)++)] = tempHP;
  271.     patableAHP[(*processedNP)] = (struct padata *) NULL;
  272.     tempHP->addressL = valueL;
  273.     strncpy( tempHP->symbolAB, symbolAB, (PA_SYM_LEN - 1));
  274.     (tempHP->symbolAB)[PA_SYM_LEN - 1] = '\0';
  275.     tempHP->hitsL = 0L;
  276.  
  277. #ifdef TEST
  278.     printf("Adding %d: %s with value %lx\n", (*processedNP),
  279.         tempHP->symbolAB, tempHP->addressL );
  280. #endif
  281.     }
  282.  
  283.     /* Enter beginning of memory symbol if there is room.  Allocate space for
  284.      * the actual symbol info. */
  285.     if ((tempHP = (struct padata *) malloc (sizeof(struct padata)))
  286.         == (struct padata *) NULL)
  287.     return(PA_NO_MEM_E);
  288.     patableAHP[((*processedNP)++)] = tempHP;
  289.     patableAHP[(*processedNP)] = (struct padata *) NULL;
  290.     tempHP->addressL = 0L;
  291.     strncpy( tempHP->symbolAB, PA_BOMSYM, (PA_SYM_LEN - 1));
  292.     (tempHP->symbolAB)[PA_SYM_LEN - 1] = '\0';
  293.     tempHP->hitsL = 0L;
  294.  
  295.     /* Enter end of memory symbol if there is room.  Allocate space for
  296.      * the actual symbol info. */
  297.     if ((tempHP = (struct padata *) malloc (sizeof(struct padata)))
  298.         == (struct padata *) NULL)
  299.     return(PA_NO_MEM_E);
  300.     patableAHP[((*processedNP)++)] = tempHP;
  301.     patableAHP[(*processedNP)] = (struct padata *) NULL;
  302.     tempHP->addressL = PA_68020_TOP;
  303.     strncpy( tempHP->symbolAB, PA_TOPSYM, (PA_SYM_LEN - 1));
  304.     (tempHP->symbolAB)[PA_SYM_LEN - 1] = '\0';
  305.     tempHP->hitsL = 0L;
  306.  
  307. #ifdef TEST
  308.     printf("Dump of unsorted table\n");
  309.     for (i = 0; i < *processedNP; i++)
  310.     {
  311.     printf("%s  %lx\n",
  312.         ((patableAHP[i])->symbolAB), ((patableAHP[i])->addressL));
  313.     }
  314.  
  315.     printf("Number of symbols to sort: %d\n", *processedNP);
  316.     printf("Size of each pointer to a symbol record %d\n", sizeof(struct padata *));
  317. #endif
  318.  
  319.     /* The map file has been read in, now sort it according to value. */
  320.     qsort(&(patableAHP[0]), *processedNP, sizeof(struct padata *), pa_addrcomp );
  321.  
  322.     /* Ok termination, return zero as a success code.  The number of symbols
  323.      * read in is returned via *processedNP. */
  324.     return(0);
  325. }
  326.  
  327. /*
  328. ** Function:    void paclear();
  329. **
  330. ** This function frees all memory allocated in the process of making a map
  331. ** table.
  332. */
  333. void
  334. paclear()
  335. {
  336.     int i;
  337.  
  338.     i = 0;
  339.     while ( patableAHP[i] != (struct padata *) NULL )
  340.     {
  341.     free( patableAHP[i] );
  342.     patableAHP[i++] = (struct padata *) NULL;
  343.     }
  344.     return;
  345. }
  346.  
  347. #ifdef TEST
  348. /*
  349. ** Function:    int main( argcN, argvAS )
  350. **
  351. ** Description:    This is a standalone tester to allow testing the map file
  352. **        reader.
  353. */    
  354. int
  355. main( argcN, argvAS )
  356. int argcN;
  357. char *argvAS[];
  358. {
  359.     FILE *mapFP;            /* File pointer to map file */
  360.     FILE *formatFP;            /* File pointer to map config. file */
  361.     int i;
  362.     int processedN;
  363.     unsigned long originL;        /* Origin of program in memory
  364.                      * relative to map values. */
  365.     int errorN;                /* Error code */
  366.  
  367.     printf("pardmap - Trial linker/memory map test reader program\n");
  368.     printf("Version %s\n", PA_VERSION);
  369.     printf("Copyright (C) 1990  Fred Motteler and Applied Microsystems Corporation\n");
  370.     if (argcN != 4)
  371.     {
  372.     printf("Usage: pardmap origin_offset filename.cfg filename.map\n");
  373.     printf("    Where: origin_offset    program origin offset\n");
  374.     printf("           filename.cfg     map file configuration file\n");
  375.     printf("           filename.map     map file\n");
  376.     exit(-100);
  377.     }
  378.     if ((mapFP = fopen(argvAS[3], "r")) == (FILE *) NULL)
  379.     {
  380.     printf("Unable to open map file\n");
  381.     exit(-101);
  382.     }
  383.     if ((formatFP = fopen(argvAS[2], "r")) == (FILE *) NULL)
  384.     {
  385.     printf("Unable to open map configuration file\n");
  386.     exit(-102);
  387.     }
  388.  
  389.     sscanf(argvAS[1], "%lx", &originL);
  390.  
  391.     if ((errorN = pardmap(mapFP, formatFP, originL, &processedN)) != 0)
  392.     {
  393.     pa_error(errorN);
  394.     exit(errorN);
  395.     }
  396.     printf("Number of symbols processed: %d\n", processedN);
  397.  
  398.     printf("Dump of sorted table\n");
  399.     for (i = 0; i < processedN; i++)
  400.     {
  401.     printf("%s  %lx  %ld\n",
  402.         ((patableAHP[i])->symbolAB),
  403.         ((patableAHP[i])->addressL),
  404.         ((patableAHP[i])->hitsL));
  405.     }
  406.  
  407.     paclear();
  408.     exit(0);
  409. }
  410. #endif
  411.  
  412.  
  413.